'''
Created on 11/06/2011

@author: Jose Rodriguez Shaw, Sebastian Caredio, Agustin Ventura
'''
import arbol

'''
Se definen metodos que devuelven la estructura de arbol en de bruijn para cada operador
cada uno de estos generadores devuelve un TElemento
'''
def genElemTrue():
    raiz = arbol.TElemento('l')
    elemento1 = arbol.TElemento('l')
    raiz.insertar(elemento1, 'right')
    elemento2 = arbol.TElemento(2)
    elemento1.insertar(elemento2, 'right')
    return raiz

def genElemFalse():
    raiz = arbol.TElemento('l')
    elemento1 = arbol.TElemento('l')
    raiz.insertar(elemento1, 'right')
    elemento2 = arbol.TElemento(1)
    elemento1.insertar(elemento2, 'right')
    return raiz

def genElemAnd():
    raiz = arbol.TElemento('l')
    elemento1 = arbol.TElemento('l')
    raiz.insertar(elemento1, 'right')
    elemento2 = arbol.TElemento('@')
    elemento1.insertar(elemento2, 'right')
    elemento3 = arbol.TElemento('@')
    elemento2.insertar(elemento3, 'left')
    elemento4 = arbol.TElemento(2)
    elemento5 = arbol.TElemento(1)
    elemento3.insertar(elemento4, 'left')
    elemento3.insertar(elemento5, 'right')
    elemento6 = genElemFalse()
    elemento2.insertar(elemento6, 'right')
    return raiz

def genElemOr():
    raiz = arbol.TElemento('l')
    elemento1 = arbol.TElemento('l')
    raiz.insertar(elemento1, 'right')
    elemento2 = arbol.TElemento('@')
    elemento1.insertar(elemento2, 'right')
    elemento3 = arbol.TElemento(2)
    elemento4 = arbol.TElemento('@')
    elemento2.insertar(elemento3, 'left')
    elemento2.insertar(elemento4, 'right')
    elemento5 = genElemTrue()
    elemento6 = arbol.TElemento(1)
    elemento4.insertar(elemento5, 'left')
    elemento4.insertar(elemento6, 'right')
    return raiz
    
def genElemNot():
    raiz = arbol.TElemento('l')
    elemento1 = arbol.TElemento('l')
    raiz.insertar(elemento1, 'right')
    elemento2 = arbol.TElemento('l')
    elemento1.insertar(elemento2, 'right')
    elemento3 = arbol.TElemento('@')
    elemento2.insertar(elemento3, 'right')   
    elemento4 = arbol.TElemento(3)
    elemento5 = arbol.TElemento('@')
    elemento3.insertar(elemento4, 'left')
    elemento3.insertar(elemento5, 'right')
    elemento6 = arbol.TElemento(1)
    elemento7 = arbol.TElemento(2)
    elemento5.insertar(elemento6, 'left')
    elemento5.insertar(elemento7, 'right')
    return raiz

def genElemXor():     
    raiz = arbol.TElemento('l')
    elemento1 = arbol.TElemento('l')
    raiz.insertar(elemento1, 'right')
    elemento2 = arbol.TElemento('l')
    elemento1.insertar(elemento2, 'right')
    elemento3 = arbol.TElemento('l')
    elemento2.insertar(elemento3, 'right')
    elemento4 = arbol.TElemento('@')
    elemento3.insertar(elemento4, 'right')
    elemento5 = arbol.TElemento(4)
    elemento6 = arbol.TElemento('@')
    elemento4.insertar(elemento5, 'left')
    elemento4.insertar(elemento6, 'right')
    elemento7 = arbol.TElemento('@')
    elemento8 = arbol.TElemento('@')
    elemento6.insertar(elemento7, 'left')
    elemento6.insertar(elemento8, 'right')
    elemento9 = arbol.TElemento(3)
    elemento10 = arbol.TElemento('@')
    elemento7.insertar(elemento9, 'left')
    elemento7.insertar(elemento10, 'right')
    elemento11 = arbol.TElemento(3)
    elemento12 = arbol.TElemento('@')
    elemento8.insertar(elemento11, 'left')
    elemento8.insertar(elemento12, 'right')
    elemento13 = arbol.TElemento(1)
    elemento14 = arbol.TElemento(2)
    elemento10.insertar(elemento13, 'left')
    elemento10.insertar(elemento14, 'right')
    elemento15 = arbol.TElemento(2)
    elemento16 = arbol.TElemento(1)
    elemento12.insertar(elemento15, 'left')
    elemento12.insertar(elemento16, 'right')
    return raiz    
    
'''
Primero lo que hacemos es pasar la formula booleana al calculo lambda en la notacion
de de bruijn y luego hacemos las reducciones.

l = lambda
@ = aplicacion
los numeros estan como enteros
''' 
def traductor(formulaBooleana):
    #evaluo primero si estoy en una hoja o no, si estoy en una hoja, analizo el valor
    #de verdad de la varible
    if (formulaBooleana.hijoIzq <> None):
        #si es diferente de nulo a la izquierda, entonces no es un NOT
        #obtengo el arbol a la izquierda del operador
        elemento1 = arbol.TElemento('@')
        if (formulaBooleana.datos == 'AND'):
            elemento2 = genElemAnd()
        elif (formulaBooleana.datos == 'OR'):
            elemento2 = genElemAnd()
        elif (formulaBooleana.datos == 'XOR'):
            elemento2 = genElemXor()
        else:
            return False
        elemento3 = arbol.TElemento('@')
        elemento1.insertar(elemento2, 'left')
        elemento1.insertar(elemento3, 'right')
        #obtengo el arbol a la derecha del operador
        elemento4 = traductor(formulaBooleana.hijoIzq)
        elemento5 = traductor(formulaBooleana.hijoDer)
        elemento3.insertar(elemento4, 'left')
        elemento3.insertar(elemento5, 'right')
    #si es nulo a la izquierda, pero diferente de nulo a la derecha, entonces es un NOT
    elif (formulaBooleana.hijoDer <> None):
        elemento1 = arbol.TElemento('@')
        if (formulaBooleana.datos == 'NOT'):
            elemento2 = genElemNot()
            elemento1.insertar(elemento2, 'left')
            elemento3 = traductor(formulaBooleana.hijoDer)
            elemento1.insertar(elemento3, 'right')
        else:  
            return False
    #si es nulo a ambos lados, entonces es una variable, donde sustituyo por el valor de
    #verdad de la misma, en de bruijn solo nos interesan los valores de verdad, no interesan
    #los nombres de las variables
    else:
        if (formulaBooleana.datos[1] == 'TRUE'):
            return genElemTrue()
        elif (formulaBooleana.datos[1] == 'FALSE'):
            return genElemFalse()
        else:
            return False
    return elemento1

def translate(formulaBooleana):
#evaluo si la profundidad es mayor a cero, de lo contrario devuelvo un arbol vacio
    if (formulaBooleana.raiz == None):
        container = arbol.TArbol()
        return container
    else:
        container = arbol.TArbol()
        #inserto la raiz en el arbol, luego el propio metodo genTern ira creando la estructura
        #de subarboles
        container.insertar(traductor(formulaBooleana.raiz))
        return container